package cn.getech.data.development.service.impl;

import cn.getech.data.development.constant.ApplyStatusEnum;
import cn.getech.data.development.constant.DataDevelopmentBizExceptionEnum;
import cn.getech.data.development.constant.PermissionTypeEnum;
import cn.getech.data.development.constant.YesOrNoEnum;
import cn.getech.data.development.entity.TableFieldInfo;
import cn.getech.data.development.entity.TableInfo;
import cn.getech.data.development.entity.dataMap.*;
import cn.getech.data.development.entity.flink.BdpRealTableField;
import cn.getech.data.development.entity.flink.BdpRealTableInfo;
import cn.getech.data.development.mapper.TableFieldInfoMapper;
import cn.getech.data.development.mapper.TableInfoMapper;
import cn.getech.data.development.mapper.dataMap.DataApplicationFieldMapper;
import cn.getech.data.development.mapper.dataMap.DataApplicationMapper;
import cn.getech.data.development.mapper.flink.BdpRealTableFieldMapper;
import cn.getech.data.development.mapper.flink.BdpRealTableInfoMapper;
import cn.getech.data.development.mapper.permission.SysRoleDataPermissionMapper;
import cn.getech.data.development.model.dto.ApplyUserListDTO;
import cn.getech.data.development.service.DataApplicationService;
import cn.getech.data.development.service.RangerDataService;
import cn.getech.data.development.utils.DataPermissionUtil;
import cn.getech.data.development.utils.permission.ApplyStatusUtil;
import cn.getech.data.intelligence.common.exception.RRException;
import cn.getech.data.intelligence.common.utils.DateUtils;
import cn.getech.data.intelligence.common.utils.PageUtils;
import cn.getech.data.intelligence.common.utils.Query;
import cn.getech.system.center.entity.SysUserEntity;
import cn.getech.system.center.model.dto.SysUserDto;
import cn.getech.system.center.service.SysUserService;
import cn.getech.system.center.utils.ShiroUtils;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import scala.annotation.meta.param;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class DataApplicationServiceImpl implements DataApplicationService {
    @Autowired
    private DataApplicationMapper dataApplicationMapper;
    @Autowired
    private TableFieldInfoMapper tableFieldInfoMapper;
    @Autowired
    private DataApplicationFieldMapper dataApplicationFieldMapper;
    @Autowired
    private SysRoleDataPermissionMapper sysRoleDataPermissionMapper;
    @Autowired
    private RangerDataService rangerDataService;

    @Autowired
    private TableInfoMapper tableInfoMapper;
    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private BdpRealTableInfoMapper realTableInfoMapper;

    @Autowired
    private BdpRealTableFieldMapper realTableFieldMapper;

    private void wrapData(DataApplication apply, Integer tableId, Integer tableType) {
        //离线
        TableInfo table = null;
        BdpRealTableInfo realTableInfo = null;
        if (tableType != null) {
            if (tableType.equals(1)) {
                table = tableInfoMapper.getTableById(tableId);
            }
            //实时
            if (tableType.equals(2)) {
                realTableInfo = realTableInfoMapper.getTableById(tableId);
            }
        }
        if (table != null) {
            apply.setTableId(tableId);
            apply.setTableName(table.getTableName());
        } else if (realTableInfo != null) {
            apply.setTableId(tableId);
            apply.setTableName(realTableInfo.getTableName());
        } else {
            throw new RRException(DataDevelopmentBizExceptionEnum.TABLE_NOT_EXIST.getMessage());
        }
    }

    @Override
    public DataApplication queryApplyInfo(Integer tableId, Long applyId, Integer tableType) {
        List<SysUserDto> userList = sysUserService.listAllUsers();
        Map<Long, String> userMap = userList.stream().collect(
                Collectors.toMap(SysUserDto::getUserId, SysUserDto::getUsername));
        if (applyId != null) {
            DataApplication apply = dataApplicationMapper.selectByPrimaryKey(applyId);
            wrapData(apply, apply.getTableId(), tableType);
            DataApplicationFieldExample param = new DataApplicationFieldExample();
            param.createCriteria().andApplyIdEqualTo(applyId);
            List<DataApplicationField> list = dataApplicationFieldMapper.selectByExample(param);
            if (CollectionUtils.isNotEmpty(list)) {
                List<Long> ids = list.stream().map(DataApplicationField::getFiledId).collect(Collectors.toList());
                apply.setFieldIds(ids);
            }
            //离线
            Set<Integer> tableIds = Collections.singleton(apply.getTableId());
            if (apply.getApplyType().equals(1)) {
                List<TableFieldInfo> fieldList = tableFieldInfoMapper.selectListByTableIds(tableIds);
                apply.setTableFieldInfos(fieldList);
            }
            //实时
            if (apply.getApplyType().equals(2)) {
                List<BdpRealTableField> bdpRealTableFields = realTableFieldMapper.selectList(new LambdaQueryWrapper<BdpRealTableField>()
                        .eq(BdpRealTableField::getDeleteFlag, 0)
                        .in(BdpRealTableField::getTableId, tableIds));
                List<TableFieldInfo> tableFieldInfos = new ArrayList<>();
                if (CollectionUtil.isNotEmpty(bdpRealTableFields)) {
                    TableFieldInfo tableFieldInfo = null;
                    for (BdpRealTableField bdpRealTableField : bdpRealTableFields) {
                        tableFieldInfo = new TableFieldInfo();
                        tableFieldInfo.setFieldType(bdpRealTableField.getFieldType());
                        tableFieldInfo.setFieldName(bdpRealTableField.getFieldName());
                        tableFieldInfo.setFieldType(bdpRealTableField.getFieldType());
                        tableFieldInfo.setId(bdpRealTableField.getId());
                        tableFieldInfo.setTableId(bdpRealTableField.getTableId());
                        tableFieldInfos.add(tableFieldInfo);
                    }
                }
                apply.setTableFieldInfos(tableFieldInfos);
            }
            if (apply.getApproveUserId() == null) {//审批人为空时 ,查询可以审批的角色
                List<Integer> ids = Collections.singletonList(apply.getTableId());

                List<Map> roleMap = null;
                if (apply.getApplyType().equals(2)) {
                    roleMap = sysRoleDataPermissionMapper.queryRealRoleByDataIds(ids);
                }
                if (apply.getApplyType().equals(1)) {
                    roleMap = sysRoleDataPermissionMapper.queryRoleByDataIds(ids);
                }
                if (CollectionUtil.isNotEmpty(roleMap)) {
                    Map<Integer, List<Map>> groupMap = roleMap.stream().filter(s->s.get("data_id")!=null)
                            .collect(Collectors.groupingBy(s -> Integer.parseInt(s.get("data_id").toString())));
                    List<Map> listMap = groupMap.get(apply.getTableId());
                    if (listMap != null) {
                        List<String> names = listMap.stream().filter(s->s.get("role_name")!=null)
                                .map(s -> s.get("role_name").toString())
                                .collect(Collectors.toList());
                        apply.setApproveUser(String.join(",", names));
                    }
                } else {//表未授权  默认为超级管理员授权
                    apply.setApproveUser("超级管理员");
                }
            }
            if (apply.getApproveUserId() != null) {
                apply.setApproveUser(userMap.get(apply.getApproveUserId()));
            }
            if (apply.getUserId() != null) {
                apply.setApplyUser(userMap.get(apply.getUserId()));
            }
            return apply;
        }
        if (tableId != null) {
            DataApplication apply = new DataApplication();
            apply.defaultValue();
            Long userId = ShiroUtils.getUserId();
            apply.setUserId(userId);
            wrapData(apply, tableId, tableType);
            if (tableType != null && tableType.equals(1)) {
                List<TableFieldInfo> fieldList = tableFieldInfoMapper.selectListByTableIds(Collections.singleton(tableId));
                apply.setTableFieldInfos(fieldList);
            }
            //实时表
            if (tableType != null && tableType.equals(2)) {
                List<BdpRealTableField> bdpRealTableFields = realTableFieldMapper.selectList(new LambdaQueryWrapper<BdpRealTableField>()
                        .in(BdpRealTableField::getTableId, tableId).eq(BdpRealTableField::getDeleteFlag, 0));
                List<TableFieldInfo> tableFieldInfos = new ArrayList<>();
                if (CollectionUtil.isNotEmpty(bdpRealTableFields)) {
                    TableFieldInfo tableFieldInfo = null;
                    for (BdpRealTableField bdpRealTableField : bdpRealTableFields) {
                        tableFieldInfo = new TableFieldInfo();
                        tableFieldInfo.setFieldType(bdpRealTableField.getFieldType());
                        tableFieldInfo.setFieldName(bdpRealTableField.getFieldName());
                        tableFieldInfo.setFieldType(bdpRealTableField.getFieldType());
                        tableFieldInfo.setId(bdpRealTableField.getId());
                        tableFieldInfo.setTableId(bdpRealTableField.getTableId());
                        tableFieldInfos.add(tableFieldInfo);
                    }
                }
                apply.setTableFieldInfos(tableFieldInfos);
            }
            return apply;
        }
        return null;
    }

    @Override
    public void saveApplyInfo(DataApplication param) {
        param.setSubmitTime(new Date());
        if (param.getEffectiveDeadline() == null) {//有效期为空  默认给六十年
            Date date = DateUtils.addDateDays(new Date(), 365 * 60);
            String s = DateUtils.format(date);
            Date deadline = DateUtils.stringToDate(s + " 23:59:59",
                    DateUtils.DATE_TIME_PATTERN);
            param.setEffectiveDeadline(deadline);
        }
        param.setApplyStatus(ApplyStatusEnum.WAIT.getType());
        if (CollectionUtils.isNotEmpty(param.getFieldIds())) {//如果有分配字段权限
            param.setDecrypt(YesOrNoEnum.YES.getValue());//则用Decrypt： 1 标识一下
        }
        /**
         * 防止重复提交多次
         */
        DataApplicationExample condition = new DataApplicationExample();
        condition.createCriteria()
                .andUserIdEqualTo(param.getUserId())
                .andApplyStatusEqualTo(ApplyStatusEnum.WAIT.getType())
                .andTableIdEqualTo(param.getTableId())
                .andApplyTypeEqualTo(param.getApplyType());
        int i = dataApplicationMapper.updateByExampleSelective(param, condition);
        if (i == 0) {
            dataApplicationMapper.insertSelective(param);
        }
        if (CollectionUtils.isNotEmpty(param.getFieldIds())) {
            List<DataApplicationField> list = new ArrayList<>();
            for (Long fieldId : param.getFieldIds()) {
                DataApplicationField field = new DataApplicationField(param.getId(), fieldId);
                list.add(field);
            }
            dataApplicationFieldMapper.batchInsert(list);
        }
        ApplyStatusUtil.addTask(param.getId(), param.getEffectiveDeadline().getTime());
    }

    @Override
    public void dataApprove(DataApplication param) {
        Long userId = ShiroUtils.getUserId();
        param.setHandleTime(new Date());
        param.setApproveUserId(userId);
        if (ApplyStatusEnum.PASS.getType().equals(param.getApplyStatus())) {//审批通过
            DataApplication apply = dataApplicationMapper.selectByPrimaryKey(param.getId());
            if (apply != null) {
                param.setApproveUserId(userId);
                dataApplicationMapper.updateByPrimaryKeySelective(param);
                apply = dataApplicationMapper.selectByPrimaryKey(param.getId());
                if (apply.getApplyType() != null && apply.getApplyType().equals(1)) {
                    // 生成ranger策略
                    DataApplicationFieldExample param2 = new DataApplicationFieldExample();
                    param2.createCriteria().andApplyIdEqualTo(param.getId());
                    List<DataApplicationField> list = dataApplicationFieldMapper.selectByExample(param2);
                    if (CollectionUtils.isNotEmpty(list)) {
                        List<Long> ids = list.stream().map(DataApplicationField::getFiledId)
                                .collect(Collectors.toList());
                        List<TableFieldInfo> fieldList = tableFieldInfoMapper.selectBatchIds(ids);
                        apply.setTableFieldInfos(fieldList);
                    }
                    rangerDataService.saveOrUpdateRangerPolicy(apply);
                }
            }
        } else if (ApplyStatusEnum.REJECT.getType().equals(param.getApplyStatus())) {
            if (StringUtils.isEmpty(param.getRejectionReason())) {
                throw new RRException(DataDevelopmentBizExceptionEnum.REASON_NO_INPUT.getMessage());
            }
            dataApplicationMapper.updateByPrimaryKeySelective(param);
        }
    }

    @Override
    public void applyRollback(RollbackParam param) {
        DataApplicationExample exam = new DataApplicationExample();
        exam.createCriteria().andIdIn(param.getApplyIds());
        List<DataApplication> list = dataApplicationMapper.selectByExample(exam);
        for (DataApplication dataApplication : list) {
            dataApplication.setRollbackTime(new Date());
            dataApplication.setRollbackReason(param.getRollbackReason());
            dataApplication.setApplyStatus(ApplyStatusEnum.ROLLBACK.getType());
        }
        dataApplicationMapper.updateBatch(list);
        //todo 回收ranger中策策略
        for (DataApplication apply : list) {
            if (apply.getApplyType().equals(1)) {
                rangerDataService.saveOrUpdateRangerPolicy(apply);
            }
        }
    }
    private void wrapParams(Map<String, Object> params){
        List<Integer> emptyIds = new ArrayList<>();
        emptyIds.add(-1);
        Integer tenantId = ShiroUtils.getTenantId();
        params.put("tenantId", tenantId);
        if (Objects.isNull(params.get("applyType"))) {
            List<Integer> offlineIds = DataPermissionUtil.getDataIds(PermissionTypeEnum.STORE.getType(), PermissionTypeEnum.ASSIGN.getType());
            if (CollectionUtils.isNotEmpty(offlineIds)) {
                params.put("offlineIds", offlineIds);
            } else {
                params.put("offlineIds", emptyIds);
            }
            List<Integer> realTableIds = DataPermissionUtil.getDataIds(PermissionTypeEnum.REAL_TABLE.getType(), PermissionTypeEnum.ASSIGN.getType());
            if (CollectionUtils.isNotEmpty(realTableIds)) {
                params.put("realTableIds", realTableIds);
            } else {
                params.put("realTableIds", emptyIds);
            }
        }
        Integer applyType = (Integer) params.get("applyType");
        //离线
        if (applyType != null && applyType.equals(1)) {
            List<Integer> offlineIds = DataPermissionUtil.getDataIds(PermissionTypeEnum.STORE.getType(),
                    PermissionTypeEnum.ASSIGN.getType());
            params.put("realTableIds", emptyIds);
            if (CollectionUtils.isNotEmpty(emptyIds)) {
                params.put("offlineIds", offlineIds);
            } else {
                params.put("offlineIds", emptyIds);
            }
        }
        //实时
        if (applyType != null && applyType.equals(2)) {
            List<Integer> offlineIds = DataPermissionUtil.getDataIds(PermissionTypeEnum.REAL_TABLE.getType(),
                    PermissionTypeEnum.ASSIGN.getType());
            params.put("offlineIds", emptyIds);
            if (CollectionUtils.isNotEmpty(offlineIds)) {
                params.put("realTableIds", offlineIds);
            } else {
                params.put("realTableIds", emptyIds);
            }
        }
    }
    /**
     * 我的数据权限 我的审批 申请人列表查询
     */
    @Override
    public Set<ApplyUserListDTO> applyUserList() {
        Map<String, Object> params = new HashMap<>();
        wrapParams(params);
        Set<ApplyUserListDTO> applyUsers = dataApplicationMapper.applyUserList(params);
        return applyUsers;
    }
    @Override
    public PageUtils approveOwnList(Map<String, Object> params) {
        wrapParams(params);
        IPage<DataApplication> page = dataApplicationMapper.approvePage((Page<DataApplication>) new Query<DataApplication>().getPage(params), params);
        if (CollectionUtils.isEmpty(page.getRecords())) {
            return new PageUtils<>(page);
        }
        for (DataApplication record : page.getRecords()) {
            if (record.getApplyType().equals(2)) {
                record.setTableAlias(null);
            }
        }
        return new PageUtils<>(page);
    }

    @Override
    public PageUtils applyOwnList(Map<String, Object> params) {
        Integer userId = ShiroUtils.getUserId().intValue();
        params.put("userId", userId);
        Integer tenantId = ShiroUtils.getTenantId();
        params.put("tenantId", tenantId);
        IPage<DataApplication> page = dataApplicationMapper.approvePage((Page<DataApplication>) new Query<DataApplication>().getPage(params), params);
        if (CollectionUtils.isEmpty(page.getRecords())) {
            new PageUtils<>(page);
        }
        for (DataApplication record : page.getRecords()) {
            if (record.getApplyType().equals(2)) {
                record.setTableAlias(null);
            }
        }
        return new PageUtils<>(page);

    }

    @Override
    public PageUtils applyRollbackList(Map<String, Object> params) {
        Long userId = ShiroUtils.getUserId();
        Integer tenantId = ShiroUtils.getTenantId();
        params.put("tenantId", tenantId);
        List<Integer> applyStatusIn = new ArrayList<>(2);
        if (userId != null) {
            if (!DataPermissionUtil.isAdmin(userId.intValue())) {
                params.put("approveUserId", userId);
            }
        }
        applyStatusIn.add(ApplyStatusEnum.PASS.getType());
        applyStatusIn.add(ApplyStatusEnum.ROLLBACK.getType());
        params.put("applyStatusIn", applyStatusIn);
        IPage<DataApplication> page = dataApplicationMapper.approvePage((Page<DataApplication>) new Query<DataApplication>().getPage(params), params);
        if (CollectionUtils.isEmpty(page.getRecords())) {
            return new PageUtils<>(page);
        }
        for (DataApplication record : page.getRecords()) {
            if (record.getApplyType().equals(2)) {
                record.setTableAlias(null);
            }
        }
        return new PageUtils<>(page);
    }

    /**
     * 离线和实时数仓项目列表查询
     *
     * @return
     */
    @Override
    public List<String> projectList(Integer tableType) {
        List<String> list = null;
        Map<String, Object> params = new HashMap<>();
        wrapParams(params);
        //离线
        if (tableType != null && tableType.equals(1)) {
            list = dataApplicationMapper.offProjectList(params);
            return list;
        }
        //实时
        if (tableType != null && tableType.equals(2)) {
            list = dataApplicationMapper.realProjectList(params);
            return list;
        }
        return null;
    }

    @Override
    public List<Map<String, Object>> listUser() {
        List<Map<String, Object>> list = new ArrayList<>();
        List<DataApplication> dataApplications = dataApplicationMapper.selectAll();
        if (CollectionUtil.isEmpty(dataApplications)) {
            return list;
        }
        List<Long> userIds = dataApplications.stream().map(DataApplication::getUserId).collect(Collectors.toList());
        List<SysUserEntity> userEntities = sysUserService.list(new LambdaQueryWrapper<SysUserEntity>().in(SysUserEntity::getUserId, userIds));
        if (CollectionUtil.isEmpty(userEntities)) {
            return list;
        }
        for (SysUserEntity userEntity : userEntities) {
            Map<String, Object> map = new HashMap<>();
            map.put("userId", userEntity.getUserId().intValue());
            map.put("userName", userEntity.getUsername());
            list.add(map);
        }
        return list;
    }




    /**
     * 权限回收 申请人列表
     */
    @Override
    public Set<ApplyUserListDTO> rollbackApplyUserList() {
        Map<String, Object> params = new HashMap<>();
        Integer tenantId = ShiroUtils.getTenantId();
        params.put("tenantId", tenantId);
        Long userId = ShiroUtils.getUserId();
        List<Integer> applyStatusIn = new ArrayList<>(2);
        applyStatusIn.add(ApplyStatusEnum.PASS.getType());
        applyStatusIn.add(ApplyStatusEnum.ROLLBACK.getType());
        params.put("applyStatusIn", applyStatusIn);
        if (userId != null) {
            if (!DataPermissionUtil.isAdmin(userId.intValue())) {
                params.put("approveUserId", userId);
            }
        }
        return dataApplicationMapper.rollbackApplyUserList(params);
    }

}

